package com.spark.modules.generation.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.spark.common.core.Result;
import com.spark.common.core.api.SparkCommonApi;
import com.spark.common.core.entity.model.DataSourceColumnsModel;
import com.spark.common.core.entity.model.DataSourceTablesModel;
import com.spark.common.core.entity.online.OnlineDataSource;
import com.spark.common.exception.SparkException;
import com.spark.common.query.QueryGenerator;
import com.spark.common.utils.DataSourceUtils;
import com.spark.common.core.entity.generation.GenModel;
import com.spark.common.core.entity.generation.GenModelFields;
import com.spark.modules.generation.entity.vo.GenModelVo;
import com.spark.modules.generation.service.IGenModelFieldsService;
import com.spark.modules.generation.service.IGenModelService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 模型Controller
 *
 * @author LYCHEE
 * @date 2025/02/24 15:23
 */
@RestController
@RequestMapping(value = "/gen/model")
public class GenModelController {

    @Resource
    private IGenModelService genModelService;
    @Resource
    private SparkCommonApi sparkCommonApi;
    @Resource
    private IGenModelFieldsService genModelFieldsService;

    /**
     * 分页列表查询
     *
     * @param genModel 模型对象
     * @param pageNo      分页
     * @param pageSize    分页
     * @return 模型列表
     */
    @GetMapping(value = "/queryPageList")
    public Result<?> queryPageList(GenModel genModel,
                                   @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                   @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
        QueryWrapper<GenModel> queryWrapper = QueryGenerator.initQueryWrapper(genModel);
        Page<GenModel> page = new Page<GenModel>(pageNo, pageSize);
        IPage<GenModel> pageList = genModelService.page(page, queryWrapper);
        return Result.ok(pageList);
    }

    /**
     * 列表查询
     *
     * @param genModel 模型对象
     * @return 模型列表
     */
    @GetMapping(value = "/queryList")
    public Result<?> queryList(GenModel genModel) {
        QueryWrapper<GenModel> queryWrapper = QueryGenerator.initQueryWrapper(genModel);
        List<GenModel> list = genModelService.list(queryWrapper);
        return Result.ok(list);
    }

    /**
     * 通过ID查询
     *
     * @param id 主键
     * @return 模型对象
     */
    @GetMapping(value = "/queryById")
    public Result<?> queryById(@RequestParam String id) {
        GenModel genModel = genModelService.getById(id);
        if (Objects.isNull(genModel)) {
            return Result.fail("数据获取失败");
        }
        return Result.ok(genModel);
    }

    /**
     * 新增
     *
     * @param vo 模型对象
     * @return 成功或失败
     */
    @Transactional(rollbackFor = {Exception.class})
    @PostMapping(value = "/add")
    public Result<?> add(@Validated @RequestBody GenModelVo vo) {
        boolean save = genModelService.save(vo);
        if (StringUtils.isNotEmpty(vo.getDataSourceId()) && save) {
            // 导入模型字段
            OnlineDataSource dataSource = sparkCommonApi.queryDataSourceById(vo.getDataSourceId());
            if (Objects.isNull(dataSource)) {
                return Result.fail("数据源异常");
            }
            // 获取数据源所有表信息
            try {
                DataSourceUtils dataSourceUtils = new DataSourceUtils(dataSource.getDbDriver(), dataSource.getDbUrl()
                        , dataSource.getDbUsername(), dataSource.getDbPassword());
                List<DataSourceTablesModel> allTablesInfo = dataSourceUtils.queryAllTablesInfo();
                if (!CollectionUtils.isEmpty(allTablesInfo)) {
                    boolean flag = false;
                    String modelName = vo.getModelCode();
                    for (DataSourceTablesModel tablesModel : allTablesInfo) {
                        if (modelName.equals(tablesModel.getTableName())) {
                            flag = true;
                            break;
                        }
                    }
                    if (!flag) {
                        throw new SparkException("数据源中暂无" + modelName + "模型信息");
                    }
                    // 获取此模型的字段信息
                    List<DataSourceColumnsModel> columnsModels = dataSourceUtils.queryTableColumnInfo(modelName);
                    if (CollectionUtils.isEmpty(columnsModels)) {
                        throw new SparkException(modelName + "模型未包含字段信息");
                    }
                    for (DataSourceColumnsModel columnsModel : columnsModels) {
                        GenModelFields genModelFields = new GenModelFields();
                        genModelFields.setModelId(vo.getId());
                        genModelFields.setFieldName(columnsModel.getColumnName());
                        genModelFields.setFieldAnnotation(columnsModel.getColumnComment());
                        genModelFields.setFieldRemark(null);
                        if (StringUtils.isNotEmpty(columnsModel.getColumnComment())) {
                            Map<String, String> remarks = cutOut(columnsModel.getColumnComment());
                            if (!CollectionUtils.isEmpty(remarks)) {
                                genModelFields.setFieldAnnotation(remarks.get("part1"));
                                genModelFields.setFieldRemark(remarks.get("part2"));
                            }
                        }
                        genModelFields.setFieldType(columnsModel.getDataType());
                        genModelFields.setFieldLength(columnsModel.getCharacterMaximumLength());
                        genModelFields.setFieldDecimalPoint(columnsModel.getNumericScale());
                        genModelFields.setFieldDefaultVal(columnsModel.getColumnDefault());
                        genModelFields.setFieldPrimaryKey("是".equals(columnsModel.getColumnKey()));
                        genModelFields.setFieldNotNull(!"是".equals(columnsModel.getIsNullable()));
                        genModelFields.setFieldUnique("是".equals(columnsModel.getIsUnique()));
                        if ("id".equals(columnsModel.getColumnName())){
                            genModelFields.setFieldSelect(0);
                        }
                        if ("create_time".equals(columnsModel.getColumnName())){
                            genModelFields.setFieldSort(1);
                            genModelFields.setFieldSortPriority(6);
                        }
                        genModelFields.setComponentName("Input");
                        if ("pid".equals(genModelFields.getFieldName())) {
                            genModelFields.setComponentName("ApiTreeSelect");
                        }
                        genModelFieldsService.save(genModelFields);
                    }
                    vo.setModelSyncStatus(0);
                    vo.setModelSyncVersions(1);
                    genModelService.updateById(vo);
                    return Result.ok("添加成功");
                }
                throw new SparkException("数据源中暂无模型信息");
            } catch (Exception e) {
                throw new SparkException(e.getMessage());
            }
        }
        return Result.flag(save);
    }

    /**
     * 编辑
     *
     * @param genModel 模型对象
     * @return 成功或失败
     */
    @PostMapping(value = "/edit")
    public Result<?> edit(@Validated @RequestBody GenModel genModel) {
        boolean update = genModelService.updateById(genModel);
        return Result.flag(update);
    }

    /**
     * 通过id删除
     *
     * @param id 主键
     * @return 成功或失败
     */
    @Transactional(rollbackFor = Exception.class)
    @DeleteMapping(value = "/delete/{id}")
    public Result<?> delete(@PathVariable(name = "id") String id) {
        // 删除模型字段
        LambdaQueryWrapper<GenModelFields> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(GenModelFields::getModelId, id);
        genModelFieldsService.remove(lambdaQueryWrapper);
        boolean update = genModelService.removeById(id);
        return Result.flag(update);
    }

    /**
     * 通过id批量删除删除
     *
     * @param ids 主键
     * @return 成功或失败
     */
    @DeleteMapping(value = "/deleteBatchByIds/{ids}")
    public Result<?> deleteBatchByIds(@PathVariable(name = "ids") String[] ids) {
        boolean update = genModelService.removeBatchByIds(Arrays.asList(ids));
        return Result.flag(update);
    }

    /**
     * 处理字段的注释
     * : 按照第一个空格分割
     * : 按照第一个中文（ 分割
     * : 按照第一个英文的 ( 分割
     *
     * @param remark 字段注释
     */
    private Map<String, String> cutOut(String remark) {
        if (StringUtils.isEmpty(remark)) {
            return null;
        }
        // 查找第一个空格的下标
        int spaceIndex = remark.indexOf(' ');
        // 查找第一个中文括号的下标
        int chineseBracketIndex = remark.indexOf('（');
        // 查找第一个英文括号的下标
        int englishBracketIndex = remark.indexOf('(');

        int minIndex = Integer.MAX_VALUE;
        char separator = ' ';
        boolean foundSeparator = false;

        if (spaceIndex != -1 && spaceIndex < minIndex) {
            minIndex = spaceIndex;
            separator = ' ';
            foundSeparator = true;
        }
        if (chineseBracketIndex != -1 && chineseBracketIndex < minIndex) {
            minIndex = chineseBracketIndex;
            separator = '（';
            foundSeparator = true;
        }
        if (englishBracketIndex != -1 && englishBracketIndex < minIndex) {
            minIndex = englishBracketIndex;
            separator = '(';
            foundSeparator = true;
        }

        if (!foundSeparator) {
            // 没有找到任何分隔符
            return null;
        }

        // 根据找到的最小下标进行分割
        String part1 = remark.substring(0, minIndex);
        String part2 = remark.substring(minIndex + 1);

        // 如果是括号，检查是否有对应的闭合括号并丢弃闭合括号及其后的部分
        if (separator == '（') {
            int closingChineseBracketIndex = part2.indexOf('）');
            if (closingChineseBracketIndex != -1) {
                part2 = part2.substring(0, closingChineseBracketIndex);
            }
        } else if (separator == '(') {
            int closingEnglishBracketIndex = part2.indexOf(')');
            if (closingEnglishBracketIndex != -1) {
                part2 = part2.substring(0, closingEnglishBracketIndex);
            }
        }

        // 返回结果
        Map<String, String> result = new HashMap<>();
        result.put("part1", part1);
        result.put("part2", part2);
        return result;
    }

    /**
     * 是否已经存在模型名称
     *
     * @param modelName 模型名称
     * @return 是否存在
     */
    @GetMapping(value = "/existModelName")
    public Result<?> existModelName(@RequestParam String modelName) {
        return genModelService.existModelName(modelName);
    }

    /**
     * 同步模型结构
     *
     * @param modelId 模型ID
     * @return 是否成功
     */
    @GetMapping(value = "/syncModel")
    public Result<?> syncModel(@RequestParam String modelId) {
        return genModelService.syncModel(modelId);
    }

    /**
     * 通过数据源编码查询数据库中的表
     *
     * @param id 数据源编码
     * @return 数据源信息
     */
    @GetMapping(value = "/queryTableList")
    public Result<?> queryTableList(String id) {
        if (StringUtils.isEmpty(id)) {
            return Result.fail("请选择数据源或数据库");
        }
        OnlineDataSource dataSource = sparkCommonApi.queryDataSourceById(id);
        if (Objects.isNull(dataSource)) {
            return Result.ok();
        }
        try {
            List<DataSourceTablesModel> allTablesInfo = new DataSourceUtils(dataSource.getDbDriver(), dataSource.getDbUrl()
                    , dataSource.getDbUsername(), dataSource.getDbPassword()).queryAllTablesInfo();
            if (!CollectionUtils.isEmpty(allTablesInfo)) {
                List<GenModel> existTableNames = genModelService.list();
                Set<String> existingTableNamesSet = existTableNames.stream()
                        .map(GenModel::getModelCode)
                        .collect(Collectors.toSet());
                for (DataSourceTablesModel tablesModel : allTablesInfo) {
                    // 判断表是否已经存在于existTableNames中
                    boolean exists = existingTableNamesSet.contains(tablesModel.getTableName());
                    // 如果不存在，则设置 "alreadyImport" 标志为 "1"，否则设置为 "0"
                    tablesModel.setAlreadyImport(exists ? 0 : 1);
                }
            }
            return Result.ok(allTablesInfo);
        } catch (Exception e) {
            return Result.fail(e.getMessage());
        }
    }

}
